class StorageManager {
  static STORAGE_KEY = 'elementControllerRules';
  static VERSION_KEY = 'elementControllerVersion';
  static CURRENT_VERSION = '1.0.0';

  static async initialize() {
    const version = await this.getVersion();
    if (version !== this.CURRENT_VERSION) {
      await this.migrate(version);
    }
  }

  static async getVersion() {
    try {
      const result = await chrome.storage.sync.get(this.VERSION_KEY);
      return result[this.VERSION_KEY] || '0.0.0';
    } catch (error) {
      console.error('Failed to get version:', error);
      return '0.0.0';
    }
  }

  static async migrate(fromVersion) {
    console.log(`Migrating from version ${fromVersion} to ${this.CURRENT_VERSION}`);
    await chrome.storage.sync.set({ [this.VERSION_KEY]: this.CURRENT_VERSION });
  }

  static async getRules() {
    try {
      const result = await chrome.storage.sync.get(this.STORAGE_KEY);
      const rules = result[this.STORAGE_KEY];
      
      if (!rules || !Array.isArray(rules.urlRules)) {
        return { urlRules: [] };
      }
      
      return rules;
    } catch (error) {
      console.error('Failed to get rules:', error);
      return { urlRules: [] };
    }
  }

  static async saveRules(rules) {
    try {
      await chrome.storage.sync.set({ [this.STORAGE_KEY]: rules });
      return true;
    } catch (error) {
      console.error('Failed to save rules:', error);
      return false;
    }
  }

  static async addUrlRule(pattern) {
    const rules = await this.getRules();
    const newRule = {
      id: this.generateId(),
      pattern: pattern,
      enabled: true,
      elementRules: []
    };
    
    rules.urlRules.push(newRule);
    await this.saveRules(rules);
    return newRule;
  }

  static async updateUrlRule(ruleId, updates) {
    const rules = await this.getRules();
    const ruleIndex = rules.urlRules.findIndex(rule => rule.id === ruleId);
    
    if (ruleIndex === -1) {
      throw new Error(`URL rule with id ${ruleId} not found`);
    }
    
    rules.urlRules[ruleIndex] = { ...rules.urlRules[ruleIndex], ...updates };
    await this.saveRules(rules);
    return rules.urlRules[ruleIndex];
  }

  static async deleteUrlRule(ruleId) {
    const rules = await this.getRules();
    rules.urlRules = rules.urlRules.filter(rule => rule.id !== ruleId);
    await this.saveRules(rules);
    return true;
  }

  static async addElementRule(urlRuleId, selector, action = 'hide') {
    const rules = await this.getRules();
    const urlRule = rules.urlRules.find(rule => rule.id === urlRuleId);
    
    if (!urlRule) {
      throw new Error(`URL rule with id ${urlRuleId} not found`);
    }
    
    const newElementRule = {
      id: this.generateId(),
      selector: selector,
      action: action,
      enabled: true
    };
    
    urlRule.elementRules.push(newElementRule);
    await this.saveRules(rules);
    return newElementRule;
  }

  static async updateElementRule(urlRuleId, elementRuleId, updates) {
    const rules = await this.getRules();
    const urlRule = rules.urlRules.find(rule => rule.id === urlRuleId);
    
    if (!urlRule) {
      throw new Error(`URL rule with id ${urlRuleId} not found`);
    }
    
    const elementRuleIndex = urlRule.elementRules.findIndex(rule => rule.id === elementRuleId);
    if (elementRuleIndex === -1) {
      throw new Error(`Element rule with id ${elementRuleId} not found`);
    }
    
    urlRule.elementRules[elementRuleIndex] = { ...urlRule.elementRules[elementRuleIndex], ...updates };
    await this.saveRules(rules);
    return urlRule.elementRules[elementRuleIndex];
  }

  static async deleteElementRule(urlRuleId, elementRuleId) {
    const rules = await this.getRules();
    const urlRule = rules.urlRules.find(rule => rule.id === urlRuleId);
    
    if (!urlRule) {
      throw new Error(`URL rule with id ${urlRuleId} not found`);
    }
    
    urlRule.elementRules = urlRule.elementRules.filter(rule => rule.id !== elementRuleId);
    await this.saveRules(rules);
    return true;
  }

  static generateId() {
    return Date.now().toString(36) + Math.random().toString(36).substr(2);
  }

  static async clearAll() {
    try {
      await chrome.storage.sync.remove([this.STORAGE_KEY, this.VERSION_KEY]);
      return true;
    } catch (error) {
      console.error('Failed to clear storage:', error);
      return false;
    }
  }

  static onChanged(callback) {
    chrome.storage.onChanged.addListener((changes, namespace) => {
      if (namespace === 'sync' && changes[this.STORAGE_KEY]) {
        callback(changes[this.STORAGE_KEY].newValue, changes[this.STORAGE_KEY].oldValue);
      }
    });
  }
}

if (typeof window !== 'undefined') {
  window.StorageManager = StorageManager;
}